#!/usr/bin/python2.4
#  -*- coding: UTF-8 -*-
# vim: set fileencoding=UTF-8 tabstop=4 shiftwidth=4 expandtab :
# 
# +------------------------------------------------+
# | OpenCaptivePortal                              |
# |                                                |
# | For further information please see             |
# |    http://code.google.com/p/opencaptiveportal/ |
# | or                                             |
# |    http://www.switch.ch/mobile/pwlan/          |
# +------------------------------------------------+
# 

# (aka. route.php and back.php)

# TODO: 
# - iptables scripts besser machen

# config
DB_FILE='@SHAREDIR@/pwlan.db'

import os, sys, re
from pysqlite2 import dbapi2 as sqlite3

re_ipv4 = re.compile('^((\d{1,3}\.){3}\d{1,3})$')
re_ipv6 = re.compile('^([0-9a-fA-F]{1,4})(\:([0-9a-fA-F]{1,4})){7}$')

# Usage:
def usage(exit = 9):
  print "Usage: %s  add  <src_ip>  <wisp_id>" % sys.argv[0]
  print "       %s  del  <src_ip>" % sys.argv[0]
  sys.exit(exit)

try:
  assert len(sys.argv) >= 3
  cmd    = sys.argv[1]
  src_ip = sys.argv[2] # TODO: IP ueberpruefen
  assert cmd in ("add", "del")
  assert (re_ipv4.match(src_ip) or 
          re_ipv6.match(src_ip))
  if cmd == "add":
    assert len(sys.argv) == 4
    wisp_id = int(sys.argv[3])
except:
  usage(9)

# DB aufmachen
try:
  con = sqlite3.connect(DB_FILE)
except:
  print "%s: Cannot open SQLite DB" % sys.argv[0]
  sys.exit(9)
cur = con.cursor()

########################################
def route(src_ip, provider):
  """
  Add a route for src_ip to Provider with provider
  """
  cur.execute("""SELECT id FROM provider WHERE name = ?""", (provider,))
  provider_id = cur.fetchone()[0]
  if not provider_id:
    return 9
  ret = os.system("""
      sudo /sbin/iptables -t mangle -A PREROUTING -s %s -j MARK --set-mark %i
    """ % (src_ip, int(provider_id)))
  if ret == 0:
    ret = ret | back(src_ip)
    cur.execute("""INSERT INTO active_routes 
        (src_ip, provider_id) VALUES (?, ?)""", (src_ip, int(provider_id)))
    con.commit()
  return ret

def back(src_ip):
  """
  Delete _ALL_ routes for src_ip
  """
  # Solange versuchen diese Route zu loeschen, bis es keine mehr in den iptables gibt:
  # no while loop (is better...)
  ret = os.system("""
      count=`sudo /sbin/iptables -t mangle -nv --list PREROUTING | grep " %s " | wc -l`
      for i in `seq 1 $count`; do
        a=`sudo /sbin/iptables --line-numbers -t mangle -nv --list PREROUTING | grep " %s " | cut -d" " -f 1 | head -n 1`;
        [ "$a" ] && sudo /sbin/iptables -t mangle -D PREROUTING $a;
      done
    """ % (src_ip, src_ip))
  cur.execute("""DELETE FROM active_routes WHERE src_ip = ?""", (src_ip,))
  con.commit()
  return ret
########################################
def exit_prog(exit = 0):
  con.commit()
  cur.close()
  con.close()
  sys.exit(exit)

if cmd == "add":
  exit_prog(route(src_ip, wisp_id))
if cmd == "del":
  exit_prog(back(src_ip))

